/*******************************************************************************
* file  : rsa key text
* creat : apleilx
* data  : 2017/03/02
		: 签名实际是对消息做hash类信息摘要运算，将摘要结果进行私匙加密
		: 然后将公匙、消息明文、和签名发给接收方。
		: 消息长度任意，签名长度同密匙。
*******************************************************************************/
#include "common.h"
#include "crc_ext.h"
#include "mbedtls/rsa.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "bsp_api.h"
#include "os_obj.h"
#include "sys_task.h"
#include "mbedtls/platform.h"
#include "mbedtls/bignum.h"
#include "mbedtls/sha256.h"

/*
********************************************************************************
*                              function
*******************************************************************************/
extern void * rsa_src, *rsa_enc, *rsa_dec;
#define DEV_RANDOM_THRESHOLD        32
int rsa_random_entropy_poll( void *, unsigned char *, size_t, size_t *);
static const char pers[] = "simple_rsa";
int make_hash( uu8 * buffer ,int bufLen, uu8 * hash, int hashLen);

/*
********************************************************************************
*                              assert
*******************************************************************************/
#define assert_exit(cond, ret) \
    do { if (!(cond)) { \
        printf("  !. assert: failed [line: %d, error: -0x%04X]\n", __LINE__, -ret); \
        goto cleanup; \
    } } while (0)

/*
********************************************************************************
*                              display
*******************************************************************************/
void dump_buf(char *info, uint8_t *buf, uint32_t len);
void dump_rsa_key(mbedtls_rsa_context *ctx);

int ras_key_sign(void)
{
    int ret;
    size_t olen = 0;
	unsigned char hash[32];
	
    mbedtls_rsa_context *ctx;    //RSA密钥结构体
    mbedtls_entropy_context *entropy;
    mbedtls_ctr_drbg_context *ctr_drbg;
	mbedtls_sha256_context *shaobj;
	
	dbg_print("\n\n");
	dbg_print("======================================\n");
	dbg_print("key gen + sign + verify \n");
	dbg_print("======================================\n");
	
	ctx = malloc(sizeof(mbedtls_rsa_context));
	entropy = malloc(sizeof(mbedtls_entropy_context));
	ctr_drbg = malloc(sizeof(mbedtls_ctr_drbg_context));
	shaobj = malloc(sizeof(mbedtls_sha256_context));
	
    //rsa结构体初始化
    mbedtls_entropy_init(entropy);		//初始化熵结构体
    mbedtls_ctr_drbg_init(ctr_drbg);	//初始化随机数结构体
	mbedtls_sha256_init(shaobj);
    mbedtls_rsa_init(ctx);  
    						 
	// 填充方案OAEP //SHA256做散列算法
    mbedtls_rsa_set_padding(ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
	
	// 随机数生成器
	ret = mbedtls_entropy_add_source( 
		entropy, 
		rsa_random_entropy_poll,
		NULL, 
		DEV_RANDOM_THRESHOLD,
		MBEDTLS_ENTROPY_SOURCE_STRONG );
	
	assert_exit(ret == 0, ret);
	
    ret = mbedtls_ctr_drbg_seed(
		ctr_drbg, 
		mbedtls_entropy_func, 
		entropy, 
        (const uint8_t *) pers, 
		strlen(pers));				//根据个性化字符串更新种子
	
    assert_exit(ret == 0, ret);
    dbg_print("\n  . setup rng ... ok\n");
    dbg_print("\n  ! RSA Generating large primes may take minutes! \n");
	
	// 生成RSA密钥
    ret = mbedtls_rsa_gen_key(
		ctx, 
		mbedtls_ctr_drbg_random,	//随机数生成接口
		ctr_drbg,					//随机数结构体
		1024,						//模数位长度,即密匙长度、加密数据块长度
		65537);						//公开指数0x01001
    assert_exit(ret == 0, ret);                                    
    dbg_print("\n  1. RSA generate key ... ok\n");
    dump_rsa_key(ctx);  
	
	// 检测密匙
	ret = mbedtls_rsa_check_privkey( ctx ) ;
	assert_exit(ret == 0, ret); 
		
	// HASH
	memset(rsa_src, 0, 100);
	loop_n(100) ((uu16 *)(rsa_src))[index] = index;
	ret = make_hash(rsa_src, 200, hash, 32);
	assert_exit(ret == 0, ret); 
	
    //RSA用私钥签名 输出sig签名结果
	ret = mbedtls_rsa_pkcs1_sign( 
		ctx, 
		mbedtls_ctr_drbg_random, ctr_drbg, 
		MBEDTLS_MD_SHA256,
		32, hash, rsa_enc );
   
    assert_exit(ret == 0, ret);
    dump_buf("  2. rsa generate signature:", rsa_enc, 128);
	
    //RSA公钥验签 返回0则验证成功
    ret = mbedtls_rsa_pkcs1_verify(
		ctx,  
		MBEDTLS_MD_SHA256, 
		32, hash, rsa_enc);
	
    assert_exit(ret == 0, ret);
    dbg_print("  3. rsa verify signature ... ok\n\n");
	
cleanup:
    mbedtls_rsa_free(ctx);
    mbedtls_ctr_drbg_free(ctr_drbg);
    mbedtls_entropy_free(entropy);
	mbedtls_sha256_free(shaobj);

	// 释放内存
	free(ctx);
	free(entropy);
	free(ctr_drbg);
	free(shaobj);
	
    return ret;
}

int make_hash( uu8 * buffer ,int bufLen, uu8 * hash, int hashLen)
{
    int ret = -1;
    mbedtls_md_context_t ctx;
 const mbedtls_md_info_t *md_info=mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 );
    if( md_info == NULL )
        goto cleanup;
 
    mbedtls_md_init( &ctx );
 ret = mbedtls_md_setup( &ctx, md_info, 0 );
    if( ret != 0 )
        goto cleanup;
 
 ret = mbedtls_md_starts( &ctx );
    if( ret != 0 )
        goto cleanup;
    ret = mbedtls_md_update(&ctx, buffer, bufLen );
 if( ret != 0 )
 goto cleanup;
    ret = mbedtls_md_finish( &ctx, hash );
cleanup:
    mbedtls_md_free( &ctx );
    return( ret );
}
